package com.lebang.aop;

import com.lebang.common.MemberLock;
import com.lebang.component.RedisClient;
import com.lebang.model.LockModel;
import com.lebangweb.response.Callback;
import org.aspectj.lang.JoinPoint;
import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.annotation.After;
import org.aspectj.lang.annotation.Around;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Pointcut;
import org.aspectj.lang.reflect.MethodSignature;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
import org.springframework.web.context.request.RequestContextHolder;
import org.springframework.web.context.request.ServletRequestAttributes;

import javax.servlet.http.HttpServletRequest;
import java.lang.reflect.Method;

@Aspect
@Component
public class MemberLockAop {
    private ThreadLocal<LockModel> thread=new ThreadLocal<>();


    @Autowired
    private RedisClient redisClient;

    public static String MEMBER_LOCK = "Member_LOCK:";

    @Pointcut("@annotation(com.lebang.common.MemberLock)")
    public void pointCut() {
    }

    @Around("pointCut()")
    public Object aroundMethod(ProceedingJoinPoint point) throws Throwable {
        HttpServletRequest request = ((ServletRequestAttributes) RequestContextHolder.getRequestAttributes()).getRequest();
        thread.set(new LockModel(request.getHeader("userid")));
        MethodSignature methodSignature = (MethodSignature) point.getSignature();
        Method method = methodSignature.getMethod();
        MemberLock userLoginToken = method.getAnnotation(MemberLock.class);
        try {
            boolean lock = redisClient.tryGetDistributedLock(MEMBER_LOCK+ thread.get().getMemberId(), thread.get().getUuid(), userLoginToken.ttl());
            if (!lock) {
                return Callback.fail("406", "操作频繁!", null);
            }
        } catch (Exception e) {
            e.printStackTrace();
            return Callback.fail("406", "操作频繁!", null);
        }
        return point.proceed();
    }

    @After("pointCut()")
    public void afterMethod(JoinPoint point) {
        MethodSignature methodSignature = (MethodSignature) point.getSignature();
        Method method = methodSignature.getMethod();
        MemberLock userLoginToken = method.getAnnotation(MemberLock.class);
        if(userLoginToken.automaticRelease()){
            redisClient.releaseDistributedLock(MEMBER_LOCK + thread.get().getMemberId(), thread.get().getUuid());
        }
        thread.remove();
    }


}
